#include <UnitTest++.h>
#include <yaml-cpp/yaml.h>
#include <common.hpp>
#include <Math/Vector3.hpp>

using namespace std;
using namespace zzz;

SUITE(YamlTest) {
const string file_content = ""
  "- name: Ogre\n"
  "  position:\n"
  "  - 0\n"
  "  - 5\n"
  "  - 0\n"
  "  powers:\n"
  "    - name: Club\n"
  "      damage: 10\n"
  "    - name: Fist\n"
  "      damage: 8\n"
  "- name: Dragon\n"
  "  position: [1, 0, 10]\n"
  "  powers:\n"
  "    - name: Fire Breath\n"
  "      damage: 25\n"
  "    - name: Claws\n"
  "      damage: 15\n"
  "- name: Wizard\n"
  "  position: [5, -3, 0]\n"
  "  powers:\n"
  "    - name: Acid Rain\n"
  "      damage: 50\n"
  "    - name: Staff\n"
  "      damage: 3\n";
struct Power {
  string name;
  int damage;
};
struct Monster {
  std::string name;
  Vector3f position;
  std::vector <Power> powers;
};

// now the extraction operators for these types
void operator >> (const YAML::Node& node, Vector3f& v) {
  node[0] >> v.x();
  node[1] >> v.y();
  node[2] >> v.z();
}

void operator >> (const YAML::Node& node, Power& power) {
  node["name"] >> power.name;
  node["damage"] >> power.damage;
}

void operator >> (const YAML::Node& node, Monster& monster) {
  node["name"] >> monster.name;
  node["position"] >> monster.position;
  const YAML::Node& powers = node["powers"];
  monster.powers.clear();
  for(unsigned i=0;i<powers.size();i++) {
    Power power;
    powers[i] >> power;
    monster.powers.push_back(power);
  }
}

TEST(ParseTest) {
  istringstream fin(file_content);
  YAML::Parser parser(fin);
  YAML::Node doc;
  parser.GetNextDocument(doc);
  CHECK_EQUAL(3, doc.size());

  Monster monster;
  doc[0] >> monster;
  CHECK_EQUAL(Vector3f(0,5,0), monster.position);
  CHECK_EQUAL(string("Ogre"), monster.name);
  CHECK_EQUAL(2, monster.powers.size());
  CHECK_EQUAL(string("Club"), monster.powers[0].name);
  CHECK_EQUAL(10, monster.powers[0].damage);
  CHECK_EQUAL(string("Fist"), monster.powers[1].name);
  CHECK_EQUAL(8, monster.powers[1].damage);

  doc[1] >> monster;
  CHECK_EQUAL(Vector3f(1,0,10), monster.position);
  CHECK_EQUAL(string("Dragon"), monster.name);
  CHECK_EQUAL(2, monster.powers.size());
  CHECK_EQUAL(string("Fire Breath"), monster.powers[0].name);
  CHECK_EQUAL(25, monster.powers[0].damage);
  CHECK_EQUAL(string("Claws"), monster.powers[1].name);
  CHECK_EQUAL(15, monster.powers[1].damage);

  doc[2] >> monster;
  CHECK_EQUAL(Vector3f(5,-3,0), monster.position);
  CHECK_EQUAL(string("Wizard"), monster.name);
  CHECK_EQUAL(2, monster.powers.size());
  CHECK_EQUAL(string("Acid Rain"), monster.powers[0].name);
  CHECK_EQUAL(50, monster.powers[0].damage);
  CHECK_EQUAL(string("Staff"), monster.powers[1].name);
  CHECK_EQUAL(3, monster.powers[1].damage);
}
}